#include "aerial\Game\GameObject\FlyObject\Scout.h"

#include "aerial\Game\GameObject\Equipment\Shield.h"
#include "aerial\Game\GameObject\Equipment\Propeller.h"

#include "raknet\BitStream.h"

#include <iostream>

using namespace std;

const float Scout::SpeedPowerGen = 5.f;
const float Scout::MaxArmor = 60.f;
const float Scout::MaxPower = 50.f;
const float Scout::RadiusPS = 2.f;

const float Scout::MaxShieldRadius = 2.8f;
const float Scout::MPPS = 400.f;

Scout::Scout(int id, const char* username, float x, float y, uchar side, float A)
	: FlyObject(x, y, A, id, username, side),lastRotate(0),lastCount(0),countDt(0)
	,burstType(0),countDt2(0),winType(0),lastArmor(armor),judge(0) {
	// preplace the mouse at the center of screen
	lastX = 400.f;
	lastY = 300.f;
	mouseMove = false;
	power = MaxPower;
	armor = MaxArmor;

	b2CircleShape circle;
	circle.m_radius = 0.5f;

	b2FixtureDef fixtureDef;
	fixtureDef.shape = &circle;
	fixtureDef.density = 1.f;
	fixtureDef.friction = 1.f;
	fixtureDef.restitution = 0.1f;
	body->SetLinearDamping(1.f);

	body->CreateFixture(&fixtureDef);

	shield = new Shield(MaxShieldRadius, this);
	spr = hgeResMan->GetSprite("spr.scout");
	propeller = new Propeller(this, 1.f, 0.f);
}

Scout::~Scout() {	
}

void Scout::render()
{
	bool trans = false;
	if (!toDestroy) {
		int m = status & S_M_WIN;
		if (m)
		{
			if(power>40)
			{
				winType = 1;
				power -=40;
			}
		}

		if ( winType )
		{
			countDt2++;
			if (countDt2 < 500)
			{
				trans = true;
				if (id == MeSide) spr->SetColor(0x5fffffff);
				else {
					spr->SetColor(0x1fffffff);
				}
			}
			else
			{
				spr->SetColor(0xffffffff);
				countDt2 = 0;
				winType = 0;
			}
		}
		else
		{
			if (judge)
				spr->SetColor(0xffff0000);
			else
				spr->SetColor(0xffffffff);
		}
		spr->RenderEx(T.x, T.y, A, 0.1f, 0.1f);
		shield->renderShield(T.x, T.y);
		propeller->rendPropeller();
	}
	if (side != MeSide)	{
		if (trans) fnt->SetColor(0x1f000000); 
		else fnt->SetColor(0xffff0000);
	}
	else {
		fnt->SetColor(0xffffffff); 
	}
	fnt->printf(T.x, T.y, HGETEXT_LEFT, "%s", username);
}

bool Scout::update(float dt)
{
	// power regeneration
	power += SpeedPowerGen * dt;
	if (power > MaxPower) power = MaxPower;

	move(dt);	// action move
	turn(dt);	// action rotate

	lastArmor = armor;

	// flyobject dealing with general equipment and network deviation
	FlyObject::update(dt);
	return false;
}

void Scout::move(float dt)
{
	b2Vec2 Zero( 0.f, 0.f );
	if (lastArmor != armor)
		judge = 1;
	else
		judge = 0;;
	int m = status & S_M_MOV;
	int n = status & S_M_BUR;
	if (n)
	{
		if ( power>35 )
		{
			burstType = 1;
			power -= 35;
		}
	}

	if ( burstType )
	{
		countDt++;
		if (countDt <400)
		{
			if (m) {
				b2Vec2 vD(
					GetDirection().x * MPPS / BattleHelper::getRatio() * 2, 
					GetDirection().y * MPPS / BattleHelper::getRatio() * 2
				);
				SetSpeed(vD);
				b2Vec2 vec(lastX - T.x, lastY - T.y);
				if (vec.LengthSquared() > 500.f) SetSpeed(vD);
				else SetSpeed(Zero);
			}
		}
		else
		{
			if (m) {
				b2Vec2 vD(
					GetDirection().x * MPPS / BattleHelper::getRatio(), 
					GetDirection().y * MPPS / BattleHelper::getRatio()
				);
				b2Vec2 vec(lastX - T.x, lastY - T.y);
				if (vec.LengthSquared() > 500.f) SetSpeed(vD);
				else SetSpeed(Zero);
			}
			countDt = 0;
			burstType = 0;
		}
	}
	else
	{
		if (m) {
			b2Vec2 vD(
				GetDirection().x * MPPS / BattleHelper::getRatio(), 
				GetDirection().y * MPPS / BattleHelper::getRatio()
				);
			SetSpeed(vD);
			b2Vec2 vec(lastX - T.x, lastY - T.y);
			if (vec.LengthSquared() > 500.f) SetSpeed(vD);
			else SetSpeed(Zero);
		}
	}
}

void Scout::SerializationIncrement(BitStream* p)
{
	FlyObject::SerializationIncrement(p);
	p->Write(lastX);
	p->Write(lastY);
}

void Scout::DeSerializationIncrement(BitStream* p)
{
	FlyObject::DeSerializationIncrement(p);
	p->Read(lastX);
	p->Read(lastY);
}

void Scout::SerializationFull(BitStream* p)
{
	FlyObject::SerializationFull(p);
	p->Write(lastX);
	p->Write(lastY);
}

void Scout::DeSerializationFull(BitStream* p)
{
	FlyObject::DeSerializationFull(p);
	p->Read(lastX);
	p->Read(lastY);
}

void Scout::RegulateDeviation()
{
	GameObject::RegulateDeviation();
}

void Scout::turn(float dt)
{
	int r = status & (S_M_MOV);
	if (r) 
	{
		b2Vec2 vec(lastX - T.x, lastY - T.y);
		if (vec.LengthSquared() > 500.f)
		{
			SetDirection(vec);
		}
	}
}

void Scout::processInput()
{
	mouseMove = false;
	float offsetX, offsetY;
	if ( T.x < 400 ) offsetX = 0.f;
	else if ( T.x < 3440 ) offsetX = T.x - 400.f;
	else offsetX = 3040.f;

	if (T.y < 300) offsetY = 0.f;
	else if (T.y < 780) offsetY = T.y - 300.f;
	else offsetY = 480.f;

	float newLastX, newLastY;
	hge->Input_GetMousePos(&newLastX, &newLastY);
	newLastX += offsetX;//T.x - 400;
	newLastY += offsetY;//T.y - 300;
	if (dist2(newLastX, newLastY, lastX, lastY) > 1.f) mouseMove = true;
	lastX = newLastX;
	lastY = newLastY;
	while (hge->Input_GetEvent(inputEvent))
	{
		switch (inputEvent->key)
		{
		case HGEK_LBUTTON:
			if (inputEvent->type == INPUT_MBUTTONDOWN) SetState(S_M_MOV, S_M_MOV); 
			else SetState(0, S_M_MOV);
			break;
		case HGEK_RBUTTON:
			if (Shield::available(this)) {
				if (inputEvent->type == INPUT_MBUTTONDOWN) SetState(M_SHIELD, M_SHIELD);
				else SetState(0, M_SHIELD);
			}
			break;
		case HGEK_B:
			if (inputEvent->type == INPUT_KEYDOWN) SetState(S_M_BUR, S_M_BUR);
			else SetState(0,S_M_BUR);
			break;
		case HGEK_W:
			if (inputEvent->type == INPUT_KEYDOWN) SetState(S_M_WIN, S_M_WIN);
			else SetState(0,S_M_WIN);
			break;
		}
	}
}
